 package xin.petstore.framework.cipher;

 import xin.petstore.framework.cipher.binary.Base64;
 import java.security.MessageDigest;
 import java.security.SecureRandom;
 import javax.crypto.Cipher;
 import javax.crypto.KeyGenerator;
 import javax.crypto.Mac;
 import javax.crypto.SecretKey;
 import javax.crypto.spec.SecretKeySpec;
 
 public class EncryptUtil
 {
   public static final String MD5 = "MD5";
   public static final String SHA1 = "SHA1";
   public static final String HmacMD5 = "HmacMD5";
   public static final String HmacSHA1 = "HmacSHA1";
   public static final String DES = "DES";
   public static final String AES = "AES";
   public String charset = "UTF-8";
 
   public int keysizeDES = 0;
 
   public int keysizeAES = 128;
   public static EncryptUtil me;
 
   public static EncryptUtil getInstance()
   {
     if (me == null) {
       me = new EncryptUtil();
     }
     return me;
   }
 
   private String messageDigest(String res, String algorithm)
   {
     try {
       MessageDigest md = MessageDigest.getInstance(algorithm);
       byte[] resBytes = this.charset == null ? res.getBytes() : res.getBytes(this.charset);
       return base64(md.digest(resBytes));
     } catch (Exception e) {
       e.printStackTrace();
     }
     return null;
   }
 
   private String keyGeneratorMac(String res, String algorithm, String key)
   {
     try {
       SecretKey sk = null;
       if (key == null) {
         KeyGenerator kg = KeyGenerator.getInstance(algorithm);
         sk = kg.generateKey();
       } else {
         byte[] keyBytes = this.charset == null ? key.getBytes() : key.getBytes(this.charset);
         sk = new SecretKeySpec(keyBytes, algorithm);
       }
       Mac mac = Mac.getInstance(algorithm);
       mac.init(sk);
       byte[] result = mac.doFinal(this.charset == null ? res.getBytes() : res.getBytes(this.charset));
       return base64(result);
     } catch (Exception e) {
       e.printStackTrace();
     }
     return null;
   }
 
   private String keyGeneratorES(String res, String algorithm, String key, int keysize, boolean isEncode)
   {
     try {
       KeyGenerator kg = KeyGenerator.getInstance(algorithm);
       if (keysize == 0) {
         byte[] keyBytes = this.charset == null ? key.getBytes() : key.getBytes(this.charset);
 
         SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
         secureRandom.setSeed(keyBytes);
         kg.init(secureRandom);
       }
       else if (key == null) {
         kg.init(keysize);
       } else {
         byte[] keyBytes = this.charset == null ? key.getBytes() : key.getBytes(this.charset);
         kg.init(keysize, new SecureRandom(keyBytes));
       }
       SecretKey sk = kg.generateKey();
       SecretKeySpec sks = new SecretKeySpec(sk.getEncoded(), algorithm);
       Cipher cipher = Cipher.getInstance(algorithm);
       if (isEncode) {
         cipher.init(1, sks);
         byte[] resBytes = this.charset == null ? res.getBytes() : res.getBytes(this.charset);
         return parseByte2HexStr(cipher.doFinal(resBytes));
       }
       cipher.init(2, sks);
       return new String(cipher.doFinal(parseHexStr2Byte(res)));
     }
     catch (Exception e) {
       e.printStackTrace();
     }
     return null;
   }
 
   /*private String base64(byte[] res) {
     return Base64.encode(res);
   }*/
 
   public static String parseByte2HexStr(byte[] buf)
   {
     StringBuffer sb = new StringBuffer();
     for (int i = 0; i < buf.length; i++) {
       String hex = Integer.toHexString(buf[i] & 0xFF);
       if (hex.length() == 1) {
         hex = '0' + hex;
       }
       sb.append(hex.toUpperCase());
     }
     return sb.toString();
   }
 
   public static byte[] parseHexStr2Byte(String hexStr) {
     if (hexStr.length() < 1)
       return null;
     byte[] result = new byte[hexStr.length() / 2];
     for (int i = 0; i < hexStr.length() / 2; i++) {
       int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
       int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
       result[i] = (byte)(high * 16 + low);
     }
     return result;
   }
 
   public String MD5(String res) {
     return messageDigest(res, "MD5");
   }
 
   public String MD5(String res, String key) {
     return keyGeneratorMac(res, "HmacMD5", key);
   }
 
   public String SHA1(String res) {
     return messageDigest(res, "SHA1");
   }
 
   public String SHA1(String res, String key) {
     return keyGeneratorMac(res, "HmacSHA1", key);
   }
 
   public String DESEncode(String res, String key) {
     return keyGeneratorES(res, "DES", key, this.keysizeDES, true);
   }
 
   public String DESDecode(String res, String key) {
     return keyGeneratorES(res, "DES", key, this.keysizeDES, false);
   }
 
   public String AESEncode(String res, String key) {
     return keyGeneratorES(res, "AES", key, this.keysizeAES, true);
   }
 
   public String AESDecode(String res, String key) {
     return keyGeneratorES(res, "AES", key, this.keysizeAES, false);
   }
 
   public String XORencode(String res, String key) {
     byte[] bs = res.getBytes();
     for (int i = 0; i < bs.length; i++) {
       bs[i] = (byte)(bs[i] ^ key.hashCode());
     }
     return parseByte2HexStr(bs);
   }
 
   public String XORdecode(String res, String key) {
     byte[] bs = parseHexStr2Byte(res);
     for (int i = 0; i < bs.length; i++) {
       bs[i] = (byte)(bs[i] ^ key.hashCode());
     }
     return new String(bs);
   }
 
   public int XOR(int res, String key) {
     return res ^ key.hashCode();
   }
 }